【指南】使用Ollama构建本地LLM代码分析助手(2)

2024年12月20日 由 alex 发表 43 0

在上部分中,我们构建了代码审查器的核心分析工具。现在,我们将创建一个能够有效使用这些工具的AI助手。我们将逐步介绍每个组件,解释它们是如何协同工作的。


在ClientAI中注册我们的工具

首先,我们需要使我们的工具可供AI系统使用。以下是注册工具的方法:


def create_review_tools() -> List[ToolConfig]:
    """Create the tool configurations for code review."""
    return [
        ToolConfig(
            tool=analyze_python_code,
            name="code_analyzer",
            description=(
                "Analyze Python code structure and complexity. "
                "Expects a 'code' parameter with the Python code as a string."
            ),
            scopes=["observe"],
        ),
        ToolConfig(
            tool=check_style_issues,
            name="style_checker",
            description=(
                "Check Python code style issues. "
                "Expects a 'code' parameter with the Python code as a string."
            ),
            scopes=["observe"],
        ),
        ToolConfig(
            tool=generate_docstring,
            name="docstring_generator",
            description=(
                "Generate docstring suggestions for Python code. "
                "Expects a 'code' parameter with the Python code as a string."
            ),
            scopes=["act"],
        ),
    ]


让我们来分解一下这里发生的事情:


每个工具都被封装在一个ToolConfig对象中,这个对象会告诉ClientAI:

  • tool:要调用的实际函数。
  • name:工具的唯一标识符。
  • description:工具的功能以及它期望的参数。
  • scopes:工具何时可以使用(“observe”用于分析,“act”用于生成)。


我们将工具分为两类:

  • “observe”工具(code_analyzer和style_checker)用于收集信息。
  • “act”工具(docstring_generator)用于生成新内容。


构建AI助手类

现在,我们来创建我们的AI助手。我们将设计它分步工作,模仿人类代码审查者的思考方式:


class CodeReviewAssistant(Agent):
    """An agent that performs comprehensive Python code review."""
    @observe(
        name="analyze_structure",
        description="Analyze code structure and style",
        stream=True,
    )
    def analyze_structure(self, code: str) -> str:
        """Analyze the code structure, complexity, and style issues."""
        self.context.state["code_to_analyze"] = code
        return """
        Please analyze this Python code structure and style:
        The code to analyze has been provided in the context as 'code_to_analyze'.
        Use the code_analyzer and style_checker tools to evaluate:
        1. Code complexity and structure metrics
        2. Style compliance issues
        3. Function and class organization
        4. Import usage patterns
        """


这个首要方法至关重要:

  1. @observe装饰器将此标记为一个观察步骤
  2. stream=True启用实时输出
  3. 我们将代码存储在上下文中,以便在后续步骤中访问
  4. 返回的字符串是一个提示,指导AI如何使用我们的工具


接下来,我们添加改进建议的步骤:


@think(
        name="suggest_improvements",
        description="Suggest code improvements based on analysis",
        stream=True,
    )
    def suggest_improvements(self, analysis_result: str) -> str:
        """Generate improvement suggestions based on the analysis results."""
        current_code = self.context.state.get("current_code", "")
        return f"""
        Based on the code analysis of:
        ```python
        {current_code}
        ```
        And the analysis results:
        {analysis_result}
        Please suggest specific improvements for:
        1. Reducing complexity where identified
        2. Fixing style issues
        3. Improving code organization
        4. Optimizing import usage
        5. Enhancing readability
        6. Enhancing explicitness
        """


这个方法:

使用@think来指示这是一个推理步骤,然后接收分析结果作为输入,从上下文中检索原始代码,并最终创建一个结构化的改进建议提示。


命令行界面

现在,我们来创建一个用户友好的界面。我们将此分解为几个部分:


def main():
    # 1. Set up logging
    logger = logging.getLogger(__name__)
    # 2. Configure Ollama server
    config = OllamaServerConfig(
        host="127.0.0.1",  # Local machine
        port=11434,        # Default Ollama port
        gpu_layers=35,     # Adjust based on your GPU
        cpu_threads=8,     # Adjust based on your CPU
    )


这一部分首先设置了错误日志记录,使用合理的默认配置来配置Ollama服务器,并允许自定义GPU和CPU的使用。


接下来,我们创建AI客户端和助手:


# Use context manager for Ollama server
    with OllamaManager(config) as manager:
        # Initialize ClientAI with Ollama
        client = ClientAI(
            "ollama", 
            host=f"http://{config.host}:{config.port}"
        )
        # Create code review assistant with tools
        assistant = CodeReviewAssistant(
            client=client,
            default_model="llama3",
            tools=create_review_tools(),
            tool_confidence=0.8,  # How confident the AI should be before using tools
            max_tools_per_step=2, # Maximum tools to use per step
        )


关于此设置的要点:

上下文管理器(with)确保服务器能够正确清理。


我们连接到本地的Ollama实例。


助手被配置为:

  • 使用我们的自定义工具
  • 设定工具使用的置信度阈值
  • 每步限制使用的工具数量以防止过度使用


最后,我们创建了交互循环:


print("Code Review Assistant (Local AI)")
        print("Enter Python code to review, or 'quit' to exit.")
        print("End input with '###' on a new line.")
        while True:
            try:
                print("\n" + "=" * 50 + "\n")
                print("Enter code:")
                
                # Collect code input
                code_lines = []
                while True:
                    line = input()
                    if line == "###":
                        break
                    code_lines.append(line)
                code = "\n".join(code_lines)
                if code.lower() == "quit":
                    break
                # Process the code
                result = assistant.run(code, stream=True)
                # Handle both streaming and non-streaming results
                if isinstance(result, str):
                    print(result)
                else:
                    for chunk in result:
                        print(chunk, end="", flush=True)
                print("\n")
            except Exception as e:
                logger.error(f"Unexpected error: {e}")
                print("\nAn unexpected error occurred. Please try again.")


这个界面:

  1. 在检测到“###”之前,会收集多行代码输入。
  2. 支持流式和非流式输出。
  3. 提供清晰的错误处理机制。
  4. 允许通过输入“quit”轻松退出。


接下来,我们将其制作成一个可运行的脚本:


if __name__ == "__main__":
    main()


使用助手

让我们来看看助手如何处理实际代码。让我们运行它:


python code_analyzer.py


以下是一个包含待发现问题的示例:


def calculate_total(values,tax_rate):
    Total = 0
    for Val in values:
        if Val > 0:
            if tax_rate > 0:
                Total += Val + (Val * tax_rate)
            else:
                Total += Val
    return Total


助手将分析多个方面:

  1. 结构问题(嵌套的if语句增加了复杂性、缺少类型提示、没有输入验证)。
  2. 风格问题(变量命名不一致、逗号后缺少空格、缺少文档字符串)。


文章来源:https://medium.com/@igorbenav/building-a-code-analysis-assistant-with-ollama-a-step-by-step-guide-to-local-llms-part-2-0b66ae457d0e
欢迎关注ATYUN官方公众号
商务合作及内容投稿请联系邮箱:bd@atyun.com
评论 登录
写评论取消
回复取消