@@ -27,27 +27,59 @@ def _build_repos_summary(self, repos: List[Dict]) -> str:
2727 """Build a text summary of repositories for LLM input"""
2828 summary_parts = []
2929 for i , repo in enumerate (repos , 1 ):
30+ topics = ", " .join (repo .get ("topics" , [])[:5 ]) if repo .get ("topics" ) else "无"
3031 summary_parts .append (
3132 f"{ i } . **{ repo .get ('full_name' , 'Unknown' )} ** ({ repo .get ('language' , 'Unknown' )} )\n "
3233 f" - ⭐ Stars: { repo .get ('stars' , 0 ):,} (+{ repo .get ('stars_today' , 0 ):,} today)\n "
3334 f" - 🍴 Forks: { repo .get ('forks' , 0 ):,} \n "
3435 f" - 📝 Description: { repo .get ('description' , 'No description' )} \n "
36+ f" - 🏷️ Topics: { topics } \n "
3537 f" - 🔗 URL: { repo .get ('url' , '' )} "
3638 )
3739 return "\n \n " .join (summary_parts )
3840
39- @retry (stop = stop_after_attempt (3 ), wait = wait_exponential (multiplier = 1 , min = 2 , max = 10 ))
40- def analyze_trends (self , repos : List [Dict ], analysis_type : str = "comprehensive" ) -> str :
41- """
42- Analyze trending repositories using LLM
41+ def _build_detailed_repo_info (self , repo : Dict ) -> str :
42+ """Build detailed repository info including README excerpt"""
43+ info_parts = [
44+ f"## 项目: { repo .get ('full_name' , 'Unknown' )} " ,
45+ f"- **编程语言**: { repo .get ('language' , 'Unknown' )} " ,
46+ f"- **Star 数**: { repo .get ('stars' , 0 ):,} (+{ repo .get ('stars_today' , 0 ):,} today)" ,
47+ f"- **Fork 数**: { repo .get ('forks' , 0 ):,} " ,
48+ f"- **Open Issues**: { repo .get ('open_issues' , 0 ):,} " ,
49+ f"- **License**: { repo .get ('license' , 'Unknown' )} " ,
50+ f"- **项目描述**: { repo .get ('description' , 'No description' )} " ,
51+ ]
4352
44- Args:
45- repos: List of repository dictionaries
46- analysis_type: Type of analysis - 'comprehensive', 'brief' , 'technical'
53+ # Topics
54+ if repo . get ( "topics" ):
55+ info_parts . append ( f"- **Topics**: { ' , '. join ( repo [ 'topics' ][: 10 ]) } " )
4756
48- Returns:
49- Analysis text from LLM
50- """
57+ # Languages breakdown
58+ if repo .get ("languages" ):
59+ total = sum (repo ["languages" ].values ())
60+ lang_breakdown = ", " .join ([
61+ f"{ lang } : { bytes / total * 100 :.1f} %"
62+ for lang , bytes in list (repo ["languages" ].items ())[:5 ]
63+ ])
64+ info_parts .append (f"- **语言分布**: { lang_breakdown } " )
65+
66+ # Recent commits
67+ if repo .get ("recent_commits" ):
68+ info_parts .append ("\n **最近提交**:" )
69+ for commit in repo ["recent_commits" ][:3 ]:
70+ info_parts .append (f" - [{ commit ['sha' ]} ] { commit ['message' ]} " )
71+
72+ # README excerpt
73+ if repo .get ("readme_excerpt" ):
74+ # 截取 README 的前 800 字符
75+ readme = repo ["readme_excerpt" ][:800 ]
76+ info_parts .append (f"\n **README 摘要**:\n ```\n { readme } \n ```" )
77+
78+ return "\n " .join (info_parts )
79+
80+ @retry (stop = stop_after_attempt (3 ), wait = wait_exponential (multiplier = 1 , min = 2 , max = 10 ))
81+ def analyze_trends (self , repos : List [Dict ], analysis_type : str = "comprehensive" ) -> str :
82+ """Analyze trending repositories using LLM"""
5183 repos_summary = self ._build_repos_summary (repos )
5284
5385 prompts = {
@@ -135,65 +167,84 @@ def analyze_trends(self, repos: List[Dict], analysis_type: str = "comprehensive"
135167 return response .choices [0 ].message .content
136168
137169 @retry (stop = stop_after_attempt (3 ), wait = wait_exponential (multiplier = 1 , min = 2 , max = 10 ))
138- def analyze_single_repo (self , repo : Dict ) -> str :
170+ def analyze_single_repo_detailed (self , repo : Dict ) -> str :
139171 """
140- Analyze a single repository in detail
172+ Analyze a single repository in detail with README context
141173
142174 Args:
143- repo: Repository dictionary
175+ repo: Repository dictionary with enriched data
144176
145177 Returns:
146178 Detailed analysis text
147179 """
148- prompt = f"""请对以下 GitHub 项目进行详细分析:
149-
150- 项目名称: { repo .get ('full_name' , 'Unknown' )}
151- 编程语言: { repo .get ('language' , 'Unknown' )}
152- Star 数: { repo .get ('stars' , 0 ):,}
153- 今日新增 Star: { repo .get ('stars_today' , 0 ):,}
154- Fork 数: { repo .get ('forks' , 0 ):,}
155- 项目描述: { repo .get ('description' , 'No description' )}
156- 项目链接: { repo .get ('url' , '' )}
157-
158- 请用中文提供以下分析:
159- 1. 项目定位和主要功能
160- 2. 技术特点和创新之处
161- 3. 适用场景和目标用户
162- 4. 项目优势和潜在不足
163- 5. 学习和使用建议"""
180+ repo_info = self ._build_detailed_repo_info (repo )
181+
182+ prompt = f"""请对以下 GitHub 项目进行深度分析和解读:
183+
184+ { repo_info }
185+
186+ 请用中文提供详细的项目解读,包括以下内容:
187+
188+ ### 🎯 项目定位
189+ - 这个项目是什么?解决什么问题?
190+ - 核心功能和特性有哪些?
191+
192+ ### 💡 技术亮点
193+ - 项目采用了哪些技术?有什么创新之处?
194+ - 架构设计有什么特点?
195+
196+ ### 👥 目标用户
197+ - 这个项目适合谁使用?
198+ - 有哪些典型的使用场景?
199+
200+ ### 📈 发展潜力
201+ - 基于当前数据,项目的发展趋势如何?
202+ - 社区活跃度如何?
203+
204+ ### 🔧 快速上手
205+ - 如何快速开始使用这个项目?
206+ - 有哪些学习资源推荐?
207+
208+ ### ⚠️ 注意事项
209+ - 使用时需要注意什么?
210+ - 有哪些已知的限制或问题?
211+
212+ 请确保分析基于提供的信息,内容专业且对开发者有实际帮助。"""
164213
165214 response = self .client .chat .completions .create (
166215 model = self .model ,
167216 messages = [
168217 {
169218 "role" : "system" ,
170- "content" : "你是一位专业的开源项目分析师,擅长深入分析项目的技术特点和应用价值 。"
219+ "content" : "你是一位资深的开源项目分析师和技术专家。你擅长深入分析项目的技术细节、应用价值和发展潜力。请基于提供的项目信息(包括README内容)进行准确、专业的分析 。"
171220 },
172221 {
173222 "role" : "user" ,
174223 "content" : prompt
175224 }
176225 ],
177226 temperature = 0.7 ,
178- max_tokens = 2000
227+ max_tokens = 2500
179228 )
180229
181230 return response .choices [0 ].message .content
182231
183- def generate_daily_report (self , repos : List [Dict ], date_str : str ) -> str :
232+ def generate_daily_report (self , repos : List [Dict ], date_str : str , detailed_analysis : bool = True ) -> str :
184233 """
185- Generate a complete daily report
234+ Generate a complete daily report with optional detailed project analysis
186235
187236 Args:
188237 repos: List of repository dictionaries
189- date_str: Date string for the report (e.g., '2026-01-12')
238+ date_str: Date string for the report
239+ detailed_analysis: Whether to include detailed analysis for top projects
190240
191241 Returns:
192242 Complete markdown report with Docusaurus frontmatter
193243 """
194- analysis = self .analyze_trends (repos , "comprehensive" )
244+ print ("🤖 Generating overall trend analysis..." )
245+ overall_analysis = self .analyze_trends (repos , "comprehensive" )
195246
196- # Build the complete report with Docusaurus frontmatter
247+ # Build the report
197248 report_parts = [
198249 "---" ,
199250 f"sidebar_position: 1" ,
@@ -202,48 +253,67 @@ def generate_daily_report(self, repos: List[Dict], date_str: str) -> str:
202253 "---\n " ,
203254 f"# 📈 GitHub Trending 日报 - { date_str } \n " ,
204255 f"> 本报告由 AI 自动生成,分析了 GitHub 当日 { len (repos )} 个热门项目\n " ,
205- "---\n " ,
256+ ]
257+
258+ # Table of Contents
259+ report_parts .extend ([
260+ "## 📑 目录\n " ,
261+ "- [今日热门项目列表](#-今日热门项目列表)" ,
262+ "- [AI 趋势分析](#-ai-趋势分析)" ,
263+ ])
264+
265+ if detailed_analysis :
266+ report_parts .append ("- [重点项目深度解读](#-重点项目深度解读)" )
267+
268+ report_parts .append ("\n ---\n " )
269+
270+ # Project List
271+ report_parts .extend ([
206272 "## 📋 今日热门项目列表\n " ,
207273 self ._build_repos_summary (repos ),
208274 "\n ---\n " ,
209- "## 🤖 AI 分析报告\n " ,
210- analysis ,
275+ ])
276+
277+ # Overall Analysis
278+ report_parts .extend ([
279+ "## 🤖 AI 趋势分析\n " ,
280+ overall_analysis ,
211281 "\n ---\n " ,
212- f"*Generated by GitHub Trending Reporter | Data collected at { date_str } *"
213- ]
282+ ])
283+
284+ # Detailed Analysis for Top Projects
285+ if detailed_analysis :
286+ report_parts .append ("## 🔬 重点项目深度解读\n " )
287+ report_parts .append ("> 以下是对今日 Top 5 热门项目的详细解读\n \n " )
288+
289+ # Analyze top 5 projects
290+ top_repos = repos [:5 ]
291+ for i , repo in enumerate (top_repos , 1 ):
292+ print (f"🔍 Analyzing project { i } /{ len (top_repos )} : { repo .get ('full_name' )} ..." )
293+
294+ report_parts .append (f"### { i } . { repo .get ('full_name' , 'Unknown' )} \n " )
295+ report_parts .append (f"} )\n " )
296+
297+ try :
298+ detailed = self .analyze_single_repo_detailed (repo )
299+ report_parts .append (detailed )
300+ except Exception as e :
301+ print (f" ⚠️ Error analyzing { repo .get ('full_name' )} : { e } " )
302+ report_parts .append (f"*分析生成失败: { str (e )} *" )
303+
304+ report_parts .append ("\n ---\n " )
305+
306+ # Footer
307+ report_parts .append (f"\n *Generated by GitHub Trending Reporter | Data collected at { date_str } *" )
214308
215309 return "\n " .join (report_parts )
216310
217311
218312def analyze_trending (repos : List [Dict ], analysis_type : str = "comprehensive" ) -> str :
219- """
220- Convenience function to analyze trending repositories
221-
222- Args:
223- repos: List of repository dictionaries
224- analysis_type: Type of analysis
225-
226- Returns:
227- Analysis text
228- """
313+ """Convenience function to analyze trending repositories"""
229314 analyzer = LLMAnalyzer ()
230315 return analyzer .analyze_trends (repos , analysis_type )
231316
232317
233318if __name__ == "__main__" :
234- # Test with sample data
235- sample_repos = [
236- {
237- "full_name" : "test/repo" ,
238- "language" : "Python" ,
239- "stars" : 1000 ,
240- "stars_today" : 100 ,
241- "forks" : 50 ,
242- "description" : "A test repository" ,
243- "url" : "https://github.com/test/repo"
244- }
245- ]
246-
247- analyzer = LLMAnalyzer ()
248- print ("Testing LLM Analyzer..." )
249- # Note: Will fail without valid API key
319+ print ("LLM Analyzer module - requires valid API key to test" )
0 commit comments